package com.happytoad.libs.riatrax
{
	import com.google.analytics.GATracker;
	import com.google.analytics.debug.DebugConfiguration;
	import com.google.analytics.v4.Configuration;
	
	import flash.display.DisplayObject;

	/**
	 *  The Tracker class in a custom wrapper class to allow for automatic Google Analytic tracking.
	 *
	 *  <br/><br/>
	 *  Copyright (c) 2009 HappyToad IT Consulting (<a href="http://www.happytoad.com" target="_blank">http://www.happytoad.com</a>)<br/>
     *  Created by Rich Tretola (<a href="http://blog.everythingflex.com" target="_blank">http://blog.everythingflex.com</a>)<br/>
	 *  
	 * @includeExample examples/TrackerExample.mxml 
	 */

	public class Tracker
	{
		/**
		 * @private
		 * local copy of GATracker returned from getTracker() method
		 */
		private var gaTracker:GATracker=null;		
		/**
		 * @private
		 * static copy of Tracker returned from getInstance() method
		 */
		private static var tracker:com.happytoad.libs.riatrax.Tracker = null;
		
		//----------------------------------
		//  display
		//----------------------------------	
		/**
		 * @public
		 * Storage for the gaAction property.
		 */ 
		private var _display:DisplayObject;
		/**
		 * DisplayObject to hold a reference to the object. 
		 * <br/><br/>
		 * This property should be set to "this".
		 * <br/><br/>
		 * Example:<br/>
		 * Tracker.getInstance().display=this;
		 */
		public function get display():DisplayObject
		{
			return _display;
		} 
		/**
		 *  @private
		 */
		[Inspectable(category="General", type="DisplayObject")]
		public function set display(value:DisplayObject):void
		{
			_display = value;
		}
		
		//----------------------------------
		//  account
		//----------------------------------
		/**
		 * @public
		 * Storage for the account property.
		 */ 
		private var _account:String;
		/**
		 * This String is also known as the Google UA number of your tracking code 
		 * and looks like UA-xxxxx-yy, where the x's and y's are replaced with 
		 * the numbers that correspond to your account and profile information for 
		 * the object you are tracking.
		 * <br/><br/>
		 * This is a required property and can be obtained from Google.
		 */
		public function get account():String
		{
			return _account;
		} 
		/**
		 *  @private
		 */
		[Inspectable(category="General", type="String")]
		public function set account(value:String):void
		{
			_account = value;
		}
		
		//----------------------------------
		//  mode
		//----------------------------------
		/**
		 * @public
		 * Storage for the account property.
		 */
		private var _mode:String="AS3";
		/**
		 * String, either bridge mode or AS3 mode. This mode determines how your tracking 
		 * communicates with the Analytics servers. ( Bridge | AS3 )
		 * <br/><br/>
		 * Use Bridge mode if you control both the HTML page and the Flash content. 
		 * This mode is best if you have already implemented Google Analytics (ga.js) 
		 * tracking on your website and you want to add tracking to embedded Flash content. 
		 * The bridge mode simplifies Flash-to-JavaScript communication by providing a unified 
		 * ActionScript 3 interface to the ga.js code. It provides the connection from the 
		 * ActionScript 3 calls to the Analytics JavaScript in order to make the tracking work.
		 * <br/><br/>
		 * Use AS3 mode if you control the Adobe Flash ActionScript 3 code, but you do not 
		 * control the hosting environment of your Adobe Flash application. For example, 
		 * if you are developing Flash content for distribution across many sites, then you 
		 * would use AS3 mode. AS3 mode is completely independent from the ga.js tracking code 
		 * and contains all the Analytics tracking functionality. There is no need for a separate 
		 * ga.js tracking installation with this mode. In addition, AS3 mode uses the Flash storage 
		 * mechanism to track session information for the visitor.
		 * <br/><br/>
		 * For certain DOM parameters such as language, the AS3 component tries to retrieve the 
		 * values from the browser. If the values are not present, the component either uses the 
		 * Flash equivalent value or defaults to no.
		 * <br/><br/>
		 * This property defaults to AS3
		 */
		public function get mode():String
		{
			return _mode;	
		}
		/**
		 *  @private
		 */
		[Inspectable(category="General", enumeration="AS3,Bridge", defaultValue="AS3", type="String")]
		public function set mode(value:String):void
		{
			_mode = value;
		}
		 
		//----------------------------------
		//  visualDebug
		//----------------------------------
		/**
		 * @public
		 * Storage for the account property.
		 */ 
		private var _visualDebug:Boolean=false;
		/**
		 * Boolean set to true to show visual debugging within your application. ( true | false )
		 * This can be used to test that all is working properly.
		 * <br/><br/>
		 * This property defaults to false
		 */
		public function get visualDebug():Boolean
		{
			return _visualDebug;	
		}
		/**
		 *  @private
		 */
		[Inspectable(category="General", enumeration="true,false", defaultValue="false", type="Boolean")]
		public function set visualDebug(value:Boolean):void
		{
			_visualDebug = value;
		}
		
		
		//----------------------------------
		//  config
		//----------------------------------
		/**
		 * @public
		 * Storage for the config property.
		 */ 
		 private var _config:Configuration=null;
		/**
         * Determinates the Configuration object of the tracker.
         * <br/><br/>
         * This property defaults to null
         */
         public function get config():Configuration
		{
			return _config;	
		}
		/**
		 *  @private
		 */
		[Inspectable(category="General", type="Configuration")]
		public function set config(value:Configuration):void
		{
			_config = value;
		}
		
		
		//----------------------------------
		//  debug
		//----------------------------------
		/**
		 * @public
		 * Storage for the debug property.
		 */ 
		 private var _debug:DebugConfiguration=null;
		/**
         * Determinates the DebugConfiguration object of the tracker.
         * <br/><br/>
         * This property defaults to null
         */
         public function get debug():DebugConfiguration
		{
			return _debug;	
		}
		/**
		 *  @private
		 */
		[Inspectable(category="General", type="DebugConfiguration")]
		public function set debug(value:DebugConfiguration):void
		{
			_debug = value;
		}
		
		//----------------------------------
		//  trackerCount
		//----------------------------------
		/**
         * @public
         * Holds the count of events tracked for user session.
         */
        private var _trackerCount:int=0;
        /**
         * The current total count of events tracked for user session.
         */
        public function get trackerCount():int
        {
        	return _trackerCount;
        }
        /**
		 *  @private
		 */
		private function set trackerCount(value:int):void
		{
			_trackerCount = value;
		}
        
        /**
	     *  Returns an instance of Tracker.
	     *
	     *  @return Tracker
	     */
		public static function getInstance() : com.happytoad.libs.riatrax.Tracker
		{
			if ( tracker == null )
				tracker = new com.happytoad.libs.riatrax.Tracker();
			return tracker;
	   	}
	   	/**
         * @private
         * Singleton validates required properties and throws errors or
         * returns an instance of the GATracker
         */
		private function getTracker():GATracker
		{
			if(gaTracker==null){
				var rxTracker:Tracker = Tracker.getInstance();
				var err:String="";
				if(rxTracker.display==null)err += "Tracker display:DisplayObject is null. ";
				if(rxTracker.account==null)err += "Tracker account:String is null.";
				if(err.length){
					throw new Error(err); 
					return;
				}
				gaTracker = new GATracker(rxTracker.display, 
										  rxTracker.account, 
										  rxTracker.mode, 
										  rxTracker.visualDebug, 
										  rxTracker.config, 
										  rxTracker.debug);
			}
			return gaTracker;
		}
		/**
	     *  @param category String to be passed to Google as the Category property.
	     * 
	     *  @param action String to be passed to Google as the Action property.
	     * 
	     *  @param label String to be passed to Google as the Label property.
	     * 
	     *  @param value Number to be passed to Google as the Value property
	     *
	     *  @return Boolean success or fail returned from Google.
	     *  <br/><br/>
	     *  throws Error if category or action is null
	     */
		public function trackEvent(category:String,action:String,label:String=null,value:Number=0):Boolean{
			var returnVar:Boolean;
			var err:String="";
			if(category==null)err += "category is null. ";
			if(action==null)err += "action is null.";
			if(err.length){
				throw new Error(err); 
				return;
			}
			/*
			 * if tracking successful, increment session tracker count
			 */
			if(getTracker().trackEvent(category,action,label,value)){
				returnVar = true;
				_trackerCount++;
			}
			return returnVar;
		}
	}
}